﻿using ETHotfix;
using ETModel;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using UnityEngine;
using BVector3 = BulletSharp.Math.Vector3;

namespace ZGameSurvival.Hotfix.Components {

    /// <summary>
    /// 调试信息同步助手的启动(跟随热更组件启动)
    /// </summary>
    [ObjectSystem]
    public class DebugInfoSyncAwake : AwakeSystem<DebugInfoSyncComponent> {
        public override void Awake(DebugInfoSyncComponent self) {
            self.Awake();
        }
    }
    /// <summary>
    /// 有单位销毁也需要清理一下调试信息
    /// </summary>
    [ObjectSystem]
    public class DebugInfoSyncGameUnitDestroySystem : DestroySystem<Unit> {
        public override void Destroy(Unit self) {
            Game.Scene.GetComponent<DebugInfoSyncComponent>()?.RemoveUnitRayTestLineSync(self.Id);
        }
    }

    /// <summary>
    /// 调试信息同步助手
    /// </summary>
    public class DebugInfoSyncComponent : Component {

        /// <summary>
        /// 所有需要同步给客户端显示的
        /// </summary>
        private ConcurrentDictionary<long, GizmosMesh> SyncToClientGizmosMesh = new ConcurrentDictionary<long, GizmosMesh>();
        /// <summary>
        /// 下次轮询需要广播当前连接的客户端的
        /// </summary>
        private ConcurrentDictionary<long, GizmosMesh> NextSyncToClientGizmosMesh = new ConcurrentDictionary<long, GizmosMesh>();
        private ConcurrentBag<long> RemoveGizmosMesh = new ConcurrentBag<long>();

        /// <summary>
        /// 所有需要同步给客户端显示的
        /// </summary>
        private ConcurrentDictionary<long, GizmosRayTestLine> SyncToClientGizmosRayTestLine = new ConcurrentDictionary<long, GizmosRayTestLine>();
        /// <summary>
        /// 下次轮询需要广播当前连接的客户端的
        /// </summary>
        private ConcurrentDictionary<long, GizmosRayTestLine> NextSyncToClientGizmosRayTestLine = new ConcurrentDictionary<long, GizmosRayTestLine>();
        private ConcurrentBag<long> RemoveGizmosRayTestLine = new ConcurrentBag<long>();

        private M2C_GizmosDebug ToClientMsg = new M2C_GizmosDebug();
        public int SyncInterval = 30;
        /// <summary>
        /// 更新或添加线框模型的同步
        /// </summary>
        /// <param name="id"></param>
        public void UpdateGizmosMeshSync(long id, GizmosMesh gizmosMesh) {
            SyncToClientGizmosMesh[id] = gizmosMesh;
            NextSyncToClientGizmosMesh[id] = gizmosMesh;
        }
        /// <summary>
        /// 移除线框模型的同步
        /// </summary>
        /// <param name="id"></param>
        public void RemoveGizmosMeshSync(long id) {
            RemoveGizmosMesh.Add(id);
            GizmosMesh v;
            SyncToClientGizmosMesh.TryRemove(id, out v);
        }
        /// <summary>
        /// 更新或添加相框模型的同步
        /// </summary>
        /// <param name="id"></param>
        /// <param name="unitInfo"></param>
        public void UpdateGizmosMeshSync(long id, UnitInfo unitInfo) {

            var groundGizmosMesh = new GizmosMesh() {
                Key = id,
            };
            groundGizmosMesh.Xs.Add(unitInfo.ShapeVerticesXs);
            groundGizmosMesh.Ys.Add(unitInfo.ShapeVerticesYs);
            groundGizmosMesh.Zs.Add(unitInfo.ShapeVerticesZs);
            groundGizmosMesh.Indices.Add(unitInfo.ShapeIndices);
            groundGizmosMesh.SetCenterPosition(unitInfo.GetCenterPosition());
            groundGizmosMesh.SetRotation(unitInfo.GetRotation());
            groundGizmosMesh.SetScale(unitInfo.GetScale());
            UpdateGizmosMeshSync(id, groundGizmosMesh);
        }

        /// <summary>
        /// 更新单位检测线的同步
        /// </summary>
        /// <param name="id"></param>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        public void UpdateUnitRayTestLineSync(long id, Vector3 start, Vector3 end, Color color) {
            GizmosRayTestLine value;
            if (!SyncToClientGizmosRayTestLine.TryGetValue(id, out value) || value == null) {
                value = new GizmosRayTestLine();
                value.Key = id;
            }

            value.StartX = start.x;
            value.StartY = start.y;
            value.StartZ = start.z;
            value.EndX = end.x;
            value.EndY = end.y;
            value.EndZ = end.z;
            value.ColorR = color.R;
            value.ColorG = color.G;
            value.ColorB = color.B;

            SyncToClientGizmosRayTestLine[id] = value;
            NextSyncToClientGizmosRayTestLine[id] = value;
        }
        /// <summary>
        /// 移除单位的检测线同步
        /// </summary>
        /// <param name="id"></param>
        public void RemoveUnitRayTestLineSync(long id) {
            RemoveGizmosRayTestLine.Add(id);
            GizmosRayTestLine v;
            SyncToClientGizmosRayTestLine.TryRemove(id, out v);
        }


        public List<GizmosMesh> GetAllGizmosMesh() {
            return SyncToClientGizmosMesh.Values.ToList();
        }
        public List<GizmosRayTestLine> GetAllGizmosRayTestLine() {
            return SyncToClientGizmosRayTestLine.Values.ToList();
        }



        private Thread SyncToClientTh;
        private AutoResetEvent SyncToClientThExitEvent;
        private AutoResetEvent MainThreadCompletEvent;
        public void Awake() {
            EndThread();
            SyncToClientThExitEvent = new AutoResetEvent(false);
            MainThreadCompletEvent = new AutoResetEvent(false);
            SyncToClientTh = new Thread(new ThreadStart(SyncToClientProcess));
            SyncToClientTh.Start();
        }
        public override void Dispose() {
            EndThread();
            base.Dispose();
        }
        public void EndThread() {
            if (SyncToClientTh != null) {
                MainThreadCompletEvent.Set();
                SyncToClientThExitEvent.Set();
                if (SyncToClientTh.ThreadState != ThreadState.Stopped) {
                    try {
                        SyncToClientTh.Abort();
                    } catch { }
                }
                SyncToClientTh = null;

                MainThreadCompletEvent.Dispose();
                MainThreadCompletEvent = null;

                SyncToClientThExitEvent.Dispose();
                SyncToClientThExitEvent = null;
            }
        }
        private void SyncToClientProcess() {
            while (!SyncToClientThExitEvent.WaitOne(SyncInterval)) {
                //等待时间到了还没收到停止信号则继续下个循环
                OneThreadSynchronizationContext.Instance.Post((object state) => {
                    //给主线程去做,单线程来处理
                    OnceSyncDebugInfoToClient();
                    MainThreadCompletEvent.Set();
                }, null);
                MainThreadCompletEvent.WaitOne();
            }
        }
        private bool OnceSyncDebugInfoToClient() {


            ToClientMsg.AddGizmosMeshs.Clear();
            ToClientMsg.AddGizmosMeshs.Add(NextSyncToClientGizmosMesh.Values);
            NextSyncToClientGizmosMesh.Clear();

            ToClientMsg.RemoveGizmosMeshs.Clear();
            ToClientMsg.RemoveGizmosMeshs.Add(RemoveGizmosMesh);
            RemoveGizmosMesh.Clear();

            ToClientMsg.AddRayTestLine.Clear();
            ToClientMsg.AddRayTestLine.Add(NextSyncToClientGizmosRayTestLine.Values);
            NextSyncToClientGizmosRayTestLine.Clear();

            ToClientMsg.RemoveRayTestLine.Clear();
            ToClientMsg.RemoveRayTestLine.Add(RemoveGizmosRayTestLine);
            RemoveGizmosRayTestLine.Clear();

            if (ToClientMsg.AddGizmosMeshs.Count > 0 || ToClientMsg.RemoveGizmosMeshs.Count > 0
                || ToClientMsg.AddRayTestLine.Count > 0 || ToClientMsg.RemoveRayTestLine.Count > 0) {
                ToClientMsg.MapBroadcastAllPlayers();
                return true;
            }
            return false;

        }
    }
}
